﻿using System;
using System.Linq;
using System.Reflection;

namespace RestUpMVC.Resource
{
    internal class ResourceControllerResolver : IResourceMetaDataResolver
    {
        #region Implementation of IResourceMetaDataResolver

        public void ResolveMetaData(Type resourceType, ResourceMetaData resourceMetaData)
        {
            if (resourceType == null) throw new ArgumentNullException("resourceType");
            if (resourceMetaData == null) throw new ArgumentNullException("resourceMetaData");

            Type resourceControllerType = FindResourceController(resourceType);
            if (null==resourceControllerType)
            {
                throw new ResourceControllerNotFoundException();
            }

            resourceMetaData.ControllerType = resourceControllerType;

            resourceMetaData.AllowList = IsResourceOperationAvailable(resourceControllerType, "List");
            resourceMetaData.AllowGet = IsResourceOperationAvailable(resourceControllerType, "Get");
            resourceMetaData.AllowPut = IsResourceOperationAvailable(resourceControllerType, "Put");
            resourceMetaData.AllowPost = IsResourceOperationAvailable(resourceControllerType, "Post");
            resourceMetaData.AllowDelete = IsResourceOperationAvailable(resourceControllerType, "Delete");
        }

        private static bool IsResourceOperationAvailable(Type resourceControllerType, string operation)
        {
            return resourceControllerType
                .GetMethods()
                .Any(x => x.Name.Equals(operation, StringComparison.OrdinalIgnoreCase));
        }

        private static Type FindResourceController(Type resourceType)
        {
            string targetControllerName = resourceType.Name + "controller";
            Type foundController = null;
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foundController = assembly.GetTypes().Where(x => x.Name.Equals(targetControllerName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
                if (foundController != null)
                {
                    break;
                }
            }
            return foundController;
        }

        #endregion
    }
}